package com.ruoyi.gateway.handler;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.exception.CaptchaException;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.gateway.config.properties.CaptchaProperties;
import com.ruoyi.gateway.constant.Constant;
import com.ruoyi.gateway.service.ISmsCodeService;
import com.ruoyi.gateway.service.ValidateCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.util.concurrent.TimeUnit;


/**
 * 短信验证码获取
 *
 * @author : 小胖
 * @version : 0.0.1
 * @date : 2022/05/12  11:16
 **/
@Component
public class SmsCodeHandler implements HandlerFunction<ServerResponse>
{

    @Autowired
    private ISmsCodeService smsCodeService;

    @Autowired
    private ValidateCodeService validateCodeService;

    @Autowired
    private CaptchaProperties captchaProperties;

    @Autowired
    private RedisService redisService;

    @Override
    public Mono<ServerResponse> handle(ServerRequest serverRequest)
    {
        return serverRequest.bodyToMono(JSONObject.class)
                .map(json ->
                {
                    try
                    {
                        // 验证
                        this.check(serverRequest, json);
                        return smsCodeService.sendSmsCode(json.getString(Constant.PHONE_NUMBER));
                    }catch (CaptchaException e)
                    {
                        return AjaxResult.error(e.getMessage());
                    }
                })
                .flatMap(ajax -> ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax)));
    }

    /**
     * 验证是否可以下发短信验证码
     *
     * @param serverRequest 请求
     * @param json  请求body
     */
    private void check(ServerRequest serverRequest, JSONObject json)
    {
        // 开启了图像验证码
        if (captchaProperties.getEnabled())
        {
            // 验证图像验证码
            validateCodeService.checkCaptcha(json.getString(Constant.CODE), json.getString(Constant.UUID), false);
        }
        //TODO: 获取ip
        // 验证ip是否限制
        String verifyKey = Constants.SMS_CAPTCHA_CODE_IP_KEY + json.getString(Constant.PHONE_NUMBER);
        // 存在限制
        if (StrUtil.isNotEmpty(redisService.getCacheObject(verifyKey)))
        {
            throw new CaptchaException("操作太频繁了, 请稍后再试");
        }
        redisService.setCacheObject(verifyKey, verifyKey, Constants.SMS_CAPTCHA_CODE_IP_EXPIRATION, TimeUnit.MINUTES);
    }
}
